#include "ul_timer.h"
#include "ul_log_adapter.h"
#include "ul_malloc.h"
#include <gtest/gtest.h>
#include <iostream>
#include <vector>
using namespace LinuxNetworkUtility;
using namespace testing;
using namespace std;
char g_time_buf[sizeof(UlTimer)];
UlTimer *g_time = NULL;

char g_memory_pool_buf[sizeof(UlMemoryPool)];
UlMemoryPool *g_memory_pool = NULL;
UlModSet  g_mod_set;

void  __attribute__((constructor)) init_global_memory_pool()
{
  g_time = new(g_time_buf)UlTimer();
  EXPECT_EQ(g_time->init(10000),0);
  g_memory_pool = new(g_memory_pool_buf)UlMemoryPool(*g_time);
}

void  __attribute__((destructor)) destroy_global_memory_pool()
{
  g_memory_pool->~UlMemoryPool();
  g_memory_pool  = NULL;
  g_time->~UlTimer();
  g_time = NULL;
}

void *thread_func(void *)
{
  int64_t largest_len = 64*1024*1024;
  vector<void*> ptr_vec;
  void *ptr = 0;
  int64_t size = 0;

  for (int i = 0; i < 2; i ++)
  {
    int64_t base_len = 512;
    while (base_len < largest_len)
    {
      ptr = ul_malloc(base_len, 0, &size);
      EXPECT_NE(ptr,(void*)0);
      EXPECT_GE(size,base_len);
      UL_LOG_DEBUG("base_len:%lld,size:%lld", base_len,size);
      memset(ptr,0x00,size);
      ptr_vec.push_back(ptr);
      base_len *= 2;
    }
    for (uint32_t i = 0; i < ptr_vec.size(); i++)
    {
      ul_free(ptr_vec[i]);
      ptr_vec[i]  = NULL;
    }
  }
  return NULL;
}

int main(int argc, char **argv)
{
  EXPECT_EQ(ul_init_malloc(*g_memory_pool,*g_time,g_mod_set,100000),0);
  static const int32_t thread_num = 32;
  pthread_t threads[thread_num]; 
  for(int32_t i = 0; i < thread_num; i++)
  {
    pthread_create(threads+i, NULL, thread_func, NULL);
  }
  for(int32_t i = 0; i < thread_num; i++)
  {
    pthread_join(threads[i], NULL);
  }
}
